package main

import (
	"flag"
	"fmt"
	"github.com/go-kratos/kratos/v2/transport/http"
	"os"
	"rosesservice/internal/crontab"
	"time"

	registry "github.com/go-kratos/kratos/contrib/registry/nacos/v2"

	"rosesservice/internal/conf"
	kitlog "rosesservice/pkg/log"

	config "github.com/go-kratos/kratos/contrib/config/nacos/v2"
	"github.com/go-kratos/kratos/v2"
	kconfig "github.com/go-kratos/kratos/v2/config"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/vo"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/yaml.v3"
)

// go build -ldflags "-X main.Version=x.y.z"
var (
	// Name is the name of the compiled software.
	Name = "roses"
	// Version is the version of the compiled software.
	Version string
	// flagConf is the config flag.
	flagConf string
)

func init() {
	flag.StringVar(&flagConf, "conf", "./configs", "config path, eg: -conf config.yaml")
}

func newApp(
	logger log.Logger,
	hs *http.Server,
	gs *grpc.Server,
	reg *conf.Server,
) *kratos.App {
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(reg.Registry.Addr, reg.Registry.Port),
	}

	cc := constant.ClientConfig{
		NamespaceId:         reg.Registry.Namespace, // namespace id
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "logs",
		CacheDir:            "nacos/cache",
		LogLevel:            reg.Registry.Loglevel,
	}

	// a more graceful way to create naming client
	client, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &cc,
			ServerConfigs: sc,
		},
	)
	if err != nil {
		panic(err)
	}
	hostname, err := os.Hostname()
	if err != nil {
		panic(err)
	}
	registrar := registry.New(
		client,
		registry.WithCluster("DEFAULT"),
		registry.WithGroup("news"),
	)
	return kratos.New(
		kratos.ID(hostname),
		kratos.Name(Name),
		kratos.Version(Version),
		kratos.Metadata(map[string]string{}),
		kratos.Logger(logger),
		kratos.Server(
			hs,
			gs,
		),
		kratos.Registrar(registrar),
	)
}

func main() {
	flag.Parse()
	configLogLevel := os.Getenv("CONFIGLOGLEVEL")
	if configLogLevel == "" {
		configLogLevel = "error"
	}
	encoder := zapcore.EncoderConfig{
		TimeKey:   "t",
		LevelKey:  "level",
		NameKey:   "logger",
		CallerKey: "caller",
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.Format("2006-01-02 15:04:05"))
		},
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
	logger := kitlog.NewZapLogger(
		encoder,
		kitlog.LogLevelStr(configLogLevel),
		zap.AddStacktrace(
			zap.NewAtomicLevelAt(zapcore.ErrorLevel)),
		zap.AddCaller(),
		zap.AddCallerSkip(2),
	)
	logAddKey := []interface{}{
		"service.name", Name,
	}
	log.SetLogger(log.With(logger, logAddKey...))

	// 读取配置文件
	confighost := os.Getenv("CONFIGHOST")
	if confighost == "" {
		confighost = "127.0.0.1"
		// }
		// 	panic("请先设置配置中心地址")
	}
	namespace := os.Getenv("NAMESPACE")
	if namespace == "" {
		namespace = "public"
	}
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(confighost, 8848, constant.WithContextPath("/nacos")),
	}

	// 创建客户端配置
	cc := *constant.NewClientConfig(
		constant.WithNamespaceId(namespace),    // 命名空间 ID，public 时为空字符串
		constant.WithTimeoutMs(5000),           // 请求超时时间（毫秒）
		constant.WithNotLoadCacheAtStart(true), // 启动时不加载缓存
		constant.WithLogDir("nacos/log"),       // 日志目录
		constant.WithCacheDir("nacos/cache"),   // 缓存目录
		constant.WithLogLevel("debug"),         // 日志级别
	)

	// a more graceful way to create naming client (创建动态配置客户端)
	client, err := clients.NewConfigClient(
		vo.NacosClientParam{
			ClientConfig:  &cc,
			ServerConfigs: sc,
		},
	)
	if err != nil {
		panic(err)
	}

	nacosDataId := "config.yaml"
	nacosGroup := "qiangwei_service"

	// {
	// 	// 获取配置
	// 	content, err := client.GetConfig(vo.ConfigParam{
	// 		DataId: nacosDataId, // 配置的 DataId
	// 		Group:  nacosGroup,  // 配置的 Group
	// 	})
	// 	if err != nil {
	// 		fmt.Printf("GetConfig err: %+v\n", err)
	// 		return
	// 	}
	// 	fmt.Println("配置内容: " + content)
	// 	return
	// }

	c := kconfig.New(
		kconfig.WithSource(
			config.NewConfigSource(client, config.WithGroup(nacosGroup), config.WithDataID(nacosDataId)),
		),
		kconfig.WithDecoder(func(kv *kconfig.KeyValue, v map[string]interface{}) error {
			return yaml.Unmarshal(kv.Value, v)
		}),
	)
	if err := c.Load(); err != nil {
		panic(err)
	}

	var bc conf.Bootstrap
	if err := c.Scan(&bc); err != nil {
		panic(err)
	}

	// 日志收集服务初始化 namespace 为mq所在的命名空间(develop|testing|production), 与当前命名空间不一致时，需要修改

	// var dtmServer = "172.29.106.203:3679"
	// gid := dtmgrpc.MustGenGid("172.29.106.203:36790")
	// var busiServer = "discovery:///busi"
	// m := dtmgrpc.NewMsgGrpc(dtmServer, gid).
	//	Add(busiServer+"/api.trans.v1.Trans/TransOut", &busi.BusiReq{Amount: 30, UserId: 1}).
	//	Add(busiServer+"/api.trans.v1.Trans/TransIn", &busi.BusiReq{Amount: 30, UserId: 2})
	// m.WaitResult = true
	// err := m.Submit()
	// fmt.Println(gid)

	fmt.Println("http端口", bc.Server.Http.Addr)
	fmt.Println("grpc端口", bc.Server.Grpc.Addr)
	crt := crontab.NewCrontab()
	app, cleanup, err := initApp(&bc, bc.Server, bc.Data, logger, crt)
	if err != nil {
		panic(err)
	}
	crt.Start()
	defer func() {
		if logger.Sync != nil {
			_ = logger.Sync()
		}
		cleanup()
		crt.Stop()
	}()

	// start and wait for stop signal
	if err := app.Run(); err != nil {
		panic(err)
	}
}
